﻿using gt.TaskScheduler.Core;
using gt.TaskScheduler.Core.Components;
using log4net;
using log4net.Config;
using log4net.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace gt.TaskScheduler.Sample
{
    /*
     * 模拟业务场景：
     * 10库10表的数据，需要定时 全量处理。
     * 库：db_user_0 ..... db_user_9
     * 表：t_user_0 ....... t_user_9
     * 表：t_user_ext_0 ....... t_user_ext_9
     * 每个实例作为一个独立的节点
     * 
     **/
    class Program
    {
        private const string _redisConn = "127.0.01:6379";
        private const string _schedulerName = "sample_scanusers";
        private static ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            var loggerRepository = LogManager.CreateRepository("Log4netConsolePractice");
            XmlConfigurator.ConfigureAndWatch(loggerRepository, new FileInfo("log4net.config"));
            _logger = LogManager.GetLogger(loggerRepository.Name, typeof(Program));
            _logger.InfoFormat("测试日志写入");

            //启动2个实例
            Task task1 = Task.Run(() => StartScheduler());
            Task task2 = Task.Run(() => StartScheduler());

            Task.WaitAll(task1, task2);

            Console.ReadLine();
        }

        private static void StartScheduler()
        {
            //dataExpiredMinutes 应根据任务执行长度预估，设为预估最大值
            using (var distribute = new RedisDistributeFeature(_redisConn, 3, 10))
            {
                var options = new TaskSchedulerOptions()
                {
                    DistributeFeature = distribute,
                    Name = _schedulerName,
                    UniqueIdGenerator = new GuidUniqueIdGenerator(),
                    Threads = 2,
                    Logger = _logger
                };

                var member = new TaskSchedulerManagerBuilder(options)
                    .AddTaskHandler(GetUserSchedulers(), new UserTaskHandler())
                    .AddTaskHandler(GetUserExtSchedulers(), new UserExtTaskHandler())
                    .Build();

                member.Run();
            }
        }

        private static List<string> GetUserSchedulers()
        {
            List<string> list = new List<string>();
            for (int i = 0; i < 3; i++)
            {
                var db = string.Format("db_user_{0}", i);
                for (int j = 0; j < 10; j++)
                {
                    var tableFullName = string.Format("{0}.t_user_{1}", db, j);
                    list.Add(tableFullName);
                }
            }
            return list;
        }

        private static List<string> GetUserExtSchedulers()
        {
            List<string> list = new List<string>();
            for (int i = 0; i < 3; i++)
            {
                var db = string.Format("db_user_{0}", i);
                for (int j = 0; j < 10; j++)
                {
                    var tableFullName = string.Format("{0}.t_user_ext_{1}", db, j);
                    list.Add(tableFullName);
                }
            }
            return list;
        }
    }

    public class UserTaskHandler : ITaskHandler
    {
        public Task Execute(string tag)
        {
            return Task.Run(() =>
            {
                //数据量多的话，可以分页拉取数据，同步处理
                //拉取数据，处理业务逻辑
                Thread.Sleep(new Random().Next(1000, 5000));

                Console.WriteLine($"table:{tag} handler success.");
            });
        }
    }

    public class UserExtTaskHandler : ITaskHandler
    {
        public Task Execute(string tag)
        {
            return Task.Run(() =>
            {
                //数据量多的话，可以分页拉取数据，同步处理
                //拉取数据，处理业务逻辑
                Thread.Sleep(new Random().Next(1000, 5000));

                Console.WriteLine($"table:{tag} handler success.");
            });
        }
    }

    // 注：Guid 唯一 但不稳定，这里只是临时测试用！！！！
    public class GuidUniqueIdGenerator : ITaskSchedulerUniqueIdGenerator
    {
        public string GetUniqueName()
        {
            return Guid.NewGuid().ToString("n");
        }
    }
}
